<?php if (!defined("_ECRIRE_INC_VERSION")) return; if (class_exists('AlohacartOrderModel')) return;
/**
 * Aloha Cart
 *
 * @author     Aleksey Yaroshchuk (aleksey.yaroshchuk@gmail.com)
 * @license    GNU/GPL
 * @package    plugins
 * @subpackage alohacart
 * @copyright  (c) Aleksey Yaroshchuk 2011-2012
 * @link       http://www.spip-contrib.net/AlohaCart
 */

include_spip('classes/pdk_model');
/**
 *  Order Class
 *  This is alohacart order model
 *
 *  @author Aleksey Yaroshchuk (aleksey.yaroshchuk@gmail.com)
 */
class AlohacartOrderModel extends pdk_Model {
    /**
     *  Alohacart
     */
    private $cart;
    
    /**
     * AlohacartOrderProductModel
     */
    private $order_product_mdl;
    
    /**
     * EcataloguE ProductModel
     */
    private $product_mdl;
    
    /**
     *  id_statut of new order
     */
    public $NewOrderStatut;
    
    /**
     *  AlohacartExtensionModel
     */
    private $extension_mdl;
    
    /**
     *  EcataloguE CurrencyModel
     */
    private $currency_mdl;
    
    /**
     *  AlohacartOrderStatutModel
     */
    private $order_statut_mdl;
    
    /**
     *  Orders statuses, wich will cause products write off 
     */
    public $write_off_statuts = array(2,4);
    
    
    /**
     *  Orders statuses, wich will cause products return
     */
    public $return_statuts = array(6);
        
    public function __construct() {
        parent::__construct();
        $this->config_model();
        $this->cart = pdk_load_class('Alohacart','classes');
        $this->order_product_mdl = pdk_load_class('AlohacartOrderProductModel','classes');        
        $this->product_mdl = pdk_load_class('ProductModel', 'classes');
        $this->extension_mdl = pdk_load_class('AlohacartExtensionModel','classes');
        include_spip('classes/AlohacartException');
        $this->currency_mdl = pdk_load_class('CurrencyModel', 'classes');
        
        $this->order_statut_mdl = pdk_load_class('AlohacartOrderStatutModel', 'classes');
        
        $this->configNewOrderStatut();
        
        $write_off_statuts = lire_config('alohacart/write_off_statuts');
        if (isset($write_off_statuts) && is_array($write_off_statuts) && !empty($write_off_statuts))
            $this->write_off_statuts = $write_off_statuts;
            
        $return_statuts = lire_config('alohacart/return_statuts');
        if (isset($return_statuts) && is_array($return_statuts) && !empty($return_statuts))
            $this->return_statuts = $return_statuts;
        //var_Dump($this->write_off_statuts);    
    }
    
    function configNewOrderStatut() {
        $this->NewOrderStatut = lire_config('alohacart/default_order_statut');
        // If config isn't defined, we'll define it as firsr selected statut
        if (!$this->NewOrderStatut) {
            $order_statut = $this->order_statut_mdl->select('', '', '', 1);
        }
    }
    
    function config_model() {
        // Define main table:
        $this->main_table = 'spip_alohacart_orders';
        
        // Define primary key:
        $this->primary_key = 'id_order';
        
        // Define main table fields:
        $this->main_fields['id_order'] = 'id_order'; 
        $this->main_fields['id_statut'] = 'id_statut';
        $this->main_fields['date'] = 'date';        
        $this->main_fields['name'] = 'name';
        $this->main_fields['phone'] = 'phone';
        $this->main_fields['email'] = 'email';
        $this->main_fields['city'] = 'city';
        $this->main_fields['address'] = 'address';
        $this->main_fields['order_comments'] = 'order_comments';
        $this->main_fields['id_shipping'] = 'id_shipping';
        $this->main_fields['shipping_titre'] = 'shipping_titre';
        $this->main_fields['shipping_cost'] = 'shipping_cost';
        $this->main_fields['shipping_data'] = 'shipping_data';
        $this->main_fields['total_price'] = 'total_price';
        $this->main_fields['id_currency'] = 'id_currency';
        $this->main_fields['currency_rate'] = 'currency_rate';
        $this->main_fields['id_payment'] = 'id_payment';
        $this->main_fields['payment_titre'] = 'payment_titre';
        $this->main_fields['payment_data'] = 'payment_data';
        $this->main_fields['source'] = 'source_source';
        $this->main_fields['medium'] = 'source_medium';
        $this->main_fields['term'] = 'source_term';
        $this->main_fields['content'] = 'source_content';
        $this->main_fields['campaign'] = 'source_campaign';
        $this->main_fields['segment'] = 'source_segment';
        $this->main_fields['viewed'] = 'viewed';
        
        $this->joins['spip_alohacart_orders_statuts'] = 
            array('main_id'=>'id_statut',
                  'join_id'=>'id_statut',
                  'hard_join'=>false,
                  'join_type'=>'LEFT',
                  'fields'=>array('titre'=>'statut_titre')
                  );              
                                                                                 
         // Define validation rules:
         $this->validation->set_rules( 
            array(
               array(
                     'field'   => 'name',
                     'label'   => _T('alohacart:name'),
                     'rules'   => 'required'
                  ),
               array(
                     'field'   => 'phone',
                     'label'   => _T('alohacart:phone'),
                     'rules'   => 'required'
                  ),
               array(
                     'field'   => 'email',
                     'label'   => _T('alohacart:email'),
                     'rules'   => 'required|valid_email'
                  ),
            )
         );                                       
    }
    
    // Define test data
    public $test_data = array(
        array('id_order'=>1,'id_statut'=>1, 'date'=>'2012-02-21 15:51:05','name'=>'Test1', 'phone'=>'1234567890', 
            'email'=>'test1@test.com', 'city'=>'City1', 'address'=>'Address1', 'order_comments'=>'This is test1',
            'id_shipping'=>1, 'shipping_titre'=>'Flat shipping','shipping_cost'=>100, 'shipping_data'=>'100 грн', 'total_price'=>999, 'id_currency'=>1, 'currency_rate'=>'0.125',
            'id_payment'=>3, 'payment_titre'=>'Bank transfer','payment_data'=>'Transfer details',
            'source_source'=>'source1', 'source_medium'=>'medium1', 'source_term'=>'term1','source_content'=>'content1', 'source_campaign'=>'campaign1', 'source_segment'=>'segment1','viewed'=>1, 'statut_titre'=>'Status1'),        
        array('id_order'=>2,'id_statut'=>2, 'date'=>'2012-02-22 16:00:00','name'=>'Test2', 'phone'=>'2234567890', 
            'email'=>'test2@test.com', 'city'=>'City2', 'address'=>'Address2', 'order_comments'=>'This is test2',
            'id_shipping'=>1, 'shipping_titre'=>'Flat shipping','shipping_cost'=>100, 'shipping_data'=>'100 грн', 'total_price'=>999, 'id_currency'=>1, 'currency_rate'=>'0.125',
            'id_payment'=>3, 'payment_titre'=>'Bank transfer','payment_data'=>'Transfer details',
            'source_source'=>'source2', 'source_medium'=>'medium2', 'source_term'=>'term2','source_content'=>'content2', 'source_campaign'=>'campaign2', 'source_segment'=>'segment2','viewed'=>1,'statut_titre'=>'Status2'),
        array('id_order'=>3,'id_statut'=>3, 'date'=>'2012-02-23 17:00:00','name'=>'Test3', 'phone'=>'3334567890', 
            'email'=>'test3@test.com', 'city'=>'City3', 'address'=>'Address3', 'order_comments'=>'This is test3',
            'id_shipping'=>2, 'shipping_titre'=>'Weight shipping','shipping_cost'=>200, 'shipping_data'=>'200 грн', 'total_price'=>999, 'id_currency'=>1, 'currency_rate'=>'0.125',
            'id_payment'=>4, 'payment_titre'=>'Webmoney','payment_data'=>'Webmoney link',
            'source_source'=>'source3', 'source_medium'=>'medium3', 'source_term'=>'term3','source_content'=>'content3', 'source_campaign'=>'source_campaign3', 'source_segment'=>'segment3','viewed'=>0,'statut_titre'=>'Status3'),        
        array('id_order'=>4,'id_statut'=>4, 'date'=>'2012-02-23 18:00:00','name'=>'Test4', 'phone'=>'4444567890', 
            'email'=>'test4@test.com', 'city'=>'City4', 'address'=>'Address4', 'order_comments'=>'This is test4',
            'id_shipping'=>2, 'shipping_titre'=>'Weight shipping','shipping_cost'=>200, 'shipping_data'=>'200 грн', 'total_price'=>999, 'id_currency'=>1, 'currency_rate'=>'0.125',
            'id_payment'=>4, 'payment_titre'=>'Webmoney','payment_data'=>'Webmoney link',
            'source_source'=>'source4', 'source_medium'=>'medium4', 'source_term'=>'term4','source_content'=>'content4', 'source_campaign'=>'campaign4', 'source_segment'=>'segment4','viewed'=>0,'statut_titre'=>'Status4'),    
    );
    
    /**
     * Override parent delete funciton
     */
    public function delete($where = array()) {
         $deleted_orders = $this->select($where,'id_order');
         $result = parent::delete($where);
         
         // When order deleted, we'll delete all it's products too:
         if ($result && $deleted_orders) {
            foreach ($deleted_orders as $del_order)
                $result = $this->order_product_mdl->delete('id_order='.$del_order['id_order']);
         }
         return $result;
    }
    
    /**
     * Override parent update funciton
     */
     /*
    function insert($data, $clear_id = false) {
        if ($id_order = parent::insert($data, $clear_id)) {
            $this->ChangeOrderProductsQuantity('id_order='.$id_order);
        }
        return $id_order;
    }*/
    
    /**
     * Override parent update funciton
     */
    public function update($where = array(), $data = array()) {
        if ($return = parent::update($where, $data)) {
            // If $data contains statuses that cause write off of products and 
            // order products weren't written off yet - we must perform this operation for all orders
            $this->ChangeOrderProductsQuantity($where);
        }
        return $return;
    }
    
    /**
     *  Changes order products quantity accordind to given order data
     *  For example, if $order_data contains id_statut that cause product writting off, this function will perform this operation
     *  Алгоритм:
     *  1. Перебираем все заказы
     *  2. Если статус заказа входит в такие, при которых должно происходить списание или возврат, то ...
     *  3. Перебираем все продукты, и для каждого проверям не списан ли он уже, если требуется его списание и наоборот
     *  4. Если прошли проверку, то списываем, или возвращаем товар, и выставляем его соответствующий индикатор списания
     *  5. Повторяем процедуру для всех товаров 
     *  @param array $order_where Order's 'where' array
     */
    public function ChangeOrderProductsQuantity($order_where) {
        if (!lire_config('alohacart/automatic_write_off')) return;
        if ($orders = $this->select($order_where)) 
            foreach ($orders as $order) {
                if (in_array($order['id_statut'], $this->write_off_statuts)) 
                    $operation = 'write_off';
                else if (in_array($order['id_statut'], $this->return_statuts)) 
                    $operation = 'return';
                if (!$operation) continue;
                $order_products = $this->order_product_mdl->select('id_order='.$order['id_order']);
                foreach ($order_products as $order_product) {
                    $new_quantity = false;
                    $product = $this->product_mdl->select_by_id($order_product['id_article']);
                    // Write off
                    if (!$order_product['written_off'] && $operation == 'write_off') {
                        // Change written_off status
                        $this->order_product_mdl->update_by_id($order_product['id_order_product'], array('written_off'=>1));
                        // Write off needed products quantity
                        $new_quantity = $product['quantity'] - $order_product['quantity'];
                    }   
                    // Return 
                    else if ($order_product['written_off'] && $operation == 'return') {
                        // Change written_off status
                        $this->order_product_mdl->update_by_id($order_product['id_order_product'], array('written_off'=>0));
                        // Write off needed products quantity
                        $new_quantity = $product['quantity'] + $order_product['quantity'];
                        
                    }
                    if ($new_quantity !== false)
                        $this->product_mdl->update_by_id($order_product['id_article'], array('quantity'=>$new_quantity));
                }
            }
    }
    
    /**
     *  Creates order from products in the cart and order data
     *  @param array $data Order data array. it must contain all fields of orders table, id_shipping field, id_payment field, id_currency field
     *  @return int ID of created order
     */
    public function CreateOrder($data) {
        $order_data = $this->form_data_from_array($data);
        $order_data['date'] = date('Y-m-d H:i:s');
        $order_data['id_statut'] = $this->NewOrderStatut;
        
        // Shipping
        if (intval($order_data['id_shipping'])) {
            //throw new AlohacartException("Bad id_shipping given: ".print_r($order_data['id_shipping'], true));
            $shipping_extension = $this->extension_mdl->select_by_id(intval($order_data['id_shipping']));
            $order_data['shipping_titre'] = $shipping_extension['titre'];
            $shipping_class = $this->extension_mdl->GetExtensionClassByID($order_data['id_shipping']);          
            $order_data['shipping_cost'] = $shipping_class->GetCost();
            $order_data['shipping_data'] = $shipping_class->GetData();
        }
            
        
        // Payment
        if (intval($order_data['id_payment'])) {
            //throw new AlohacartException("Bad id_payment given: ".print_r($order_data['id_payment'], true));
            $payment_extension = $this->extension_mdl->select_by_id(intval($order_data['id_payment']));
            $order_data['payment_titre'] = $payment_extension['titre'];
            $payment_class = $this->extension_mdl->GetExtensionClassByID($order_data['id_payment']);          
            $order_data['payment_data'] = $payment_class->GetData(); 
        }
        
        $productsq = $this->cart->GetProducts();
        
        $main_currency = $this->currency_mdl->GetMainCurrency();
        
        // Total price
        $total_price = 0;
        foreach ($productsq as $id_article=>$product_quantity) {
            //$product = $this->product_mdl->select_by_id($id_article);
            //$total_price += $product['price']*$product_quantity;            
            $total_price += $this->product_mdl->GetProductPrice($id_article, $main_currency['code'])*$product_quantity;            
        }
        //$total_price = $this->currency_mdl->ConvertPriceToCurrentCurrency($total_price);
        $total_price += $order_data['shipping_cost'];
        $order_data['total_price'] = $total_price;
        
        $current_currency = $this->currency_mdl->GetCurrentCurrency();        
        $order_data['id_currency'] = $current_currency['id_currency']; 
        $order_data['currency_rate'] = $current_currency['rate'];
        
        $id_order = $this->insert($order_data);        
        if (!$id_order) return $id_order;
        
        
        
        foreach ($productsq as $id_article=>$product_quantity) {
            $order_product_data = array();
            $order_product_data['id_order'] = $id_order;
            $order_product_data['id_article'] = $id_article;
            $order_product_data['quantity'] = $product_quantity;
            
            $product = $this->product_mdl->select_by_id($id_article);
            $order_product_data['sku'] = $product['sku'];
            $order_product_data['titre'] = $product['titre'];            
            //$order_product_data['price'] = $product['price'];
            $order_product_data['price'] = $this->product_mdl->GetProductPrice($id_article, $main_currency['code']);
            
            //$order_product_data['total_price'] = $this->currency_mdl->ConvertPriceToCurrentCurrency($product['price'])*$product_quantity;
            $order_product_data['total_price'] = $order_product_data['price']*$product_quantity;
            
            $this->order_product_mdl->insert($order_product_data);
        }
        
        $this->ChangeOrderProductsQuantity('id_order='.$id_order);
        
        return $id_order;
    }
    
    /**
     *  Recalculates order's total price according to:
     *  - total prices of all products in order
     *  - shipping price
     */
    public function RecalculateOrder($id_order) {
        $order = $this->select_by_id($id_order);
        if (!isset($order) || !$order)
            throw new AlohacartException("Order #$id_order was'n found in DB!");
        
        $total_price = 0;
        
        // Total prices of all products in order
        $order_products = $this->order_product_mdl->select('id_order='.intval($id_order));
        foreach ($order_products as $product) {
            $total_price += $product['total_price'];			
        }    
        
        // Shipping price
        $total_price += $order['shipping_cost'];
        
        return $this->update_by_id($id_order, array('total_price'=>$total_price));
    } 
}
?>